/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BluetoothPlugin.h"
#include "cJSON.h"
#include <codecvt>
#include <iconv.h>
#include <locale>
REGISTER_PLUGIN_CLASS(BluetoothPlugin)
bool BluetoothPlugin::execute(const string&  action, cJSON* args, CallbackContext cbc)
{
    if(action == "getUuids") {
        m_cbc = cbc;
        string id = cJSON_GetArrayItem(args, 0)->valuestring;
        return executeArkTs("/Bluetooth/getUuids", 0, id.c_str(), "Bluetooth", cbc);
    }
    
    if(action == "connect") {
        m_cbc = cbc;
        string address = cJSON_GetArrayItem(args, 0)->valuestring;
        string uuid = cJSON_GetArrayItem(args, 1)->valuestring;
        string strConnType = cJSON_GetArrayItem(args, 2)->valuestring;
        
        cJSON* pAras = cJSON_CreateObject();
        cJSON_AddStringToObject(pAras, "address", address.c_str());
        cJSON_AddStringToObject(pAras, "uuid", uuid.c_str());
        cJSON_AddStringToObject(pAras, "connType", strConnType.c_str());
        char* pPageArgs = cJSON_Print(pAras);
        
        executeArkTs("/Bluetooth/connect", 0, pPageArgs, "Bluetooth", cbc);
        cJSON_Delete(pAras);
        free(pPageArgs);
        return true;
    }
    
    if(action == "isConnected") {
        m_cbc = cbc;
        return executeArkTs("/Bluetooth/isConnected", 0, "", "Bluetooth", cbc);
    }
    
    if(action == "startConnectionManager" || action == "stopConnectionManager") {
        cbc.success();
        return true;
    }
    
    if(action == "isConnectionManaged") {
        m_cbc = cbc;
        return executeArkTs("/Bluetooth/isConnectionManaged", 0, "", "Bluetooth", cbc);
    }
    
    if(action == "disconnect")  {
        m_cbc = cbc;
        return executeArkTs("/Bluetooth/disconnect", 0, "", "Bluetooth", cbc);
    }
    
    if(action == "write") {
        m_cbc = cbc;
        string data = cJSON_GetArrayItem(args, 0)->valuestring;
        string encoding = cJSON_GetArrayItem(args, 1)->valuestring;
        int nForceString = 1;
        if(encoding == "BMP") {
            nForceString = 0;
        }
        
        return executeArkTs("/Bluetooth/write", nForceString, data.c_str(), "Bluetooth", cbc);
    }
    if(action == "onArKTsResult") {
        return onArKTsResult(args);
    }
    return true;
}

bool BluetoothPlugin::onArKTsResult(cJSON* args)
{
    string content = cJSON_GetObjectItem(args, "content")->valuestring;
    cJSON* json = cJSON_GetObjectItem(args, "result");
    if(content == "getUuids") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            for(int i=0; i<count; i++) {
                string strIdName = cJSON_GetArrayItem(json,i)->valuestring;
                    cJSON* deviceInfo = cJSON_CreateObject();
                    const char * pTmp[1];
                    pTmp[0] = strIdName.c_str();
                    cJSON* uuids = cJSON_CreateStringArray(pTmp,1);
                    cJSON_AddStringToObject(deviceInfo, "name", "");
                    cJSON_AddStringToObject(deviceInfo, "address", "");
                    cJSON_AddItemToObject(deviceInfo, "uuids", uuids);
                    PluginResult pluginResult(PluginResult::Status::OK, deviceInfo);
                    pluginResult.setKeepCallback(true);
                    m_cbc.sendPluginResult(pluginResult);
                    cJSON_Delete(deviceInfo);
            }
        }
    }
    if(content == "connect") {
        if(json != NULL && json->type == cJSON_Array) {
            int nCode = -1;
            string strError = "";
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                strError = cJSON_GetArrayItem(json,0)->valuestring;
            }
            if(strError == "OK") {
                m_cbc.success();
                return true;
            } else {
                nCode = atoi(strError.c_str());
            }
            cJSON* pError = cJSON_CreateObject();    
            cJSON_AddStringToObject(pError, "message", "unknown");
            cJSON_AddNumberToObject(pError, "code", nCode);
            m_cbc.error(pError);
            cJSON_Delete(pError);
        }
    }
    if(content == "isConnectionManaged") {
         if(json != NULL && json->type == cJSON_Array) {
            int nSocket = -1;
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string strSocket = cJSON_GetArrayItem(json,0)->valuestring;
                nSocket = atoi(strSocket.c_str());
            }
            if(nSocket != -1) {
                PluginResult pluginResult(PluginResult::Status::OK, true);
                m_cbc.sendPluginResult(pluginResult);
                return true;
            } 
            PluginResult pluginResult(PluginResult::Status::OK, false);
            m_cbc.sendPluginResult(pluginResult);
        }
    }
    if(content == "isConnected") {
        if(json != NULL && json->type == cJSON_Array) {
            int nSocket = -1;
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string strSocket = cJSON_GetArrayItem(json,0)->valuestring;
                nSocket = atoi(strSocket.c_str());
            }
            if(nSocket != -1) {
                PluginResult pluginResult(PluginResult::Status::OK, true);
                m_cbc.sendPluginResult(pluginResult);
                return true;
            } 
            cJSON* pError = cJSON_CreateObject();    
            cJSON_AddStringToObject(pError, "message", "unknown");
            cJSON_AddNumberToObject(pError, "code", nSocket);
            m_cbc.error(pError);
            cJSON_Delete(pError);
        }
    }
    
    if(content == "disconnect") {
        if(json != NULL && json->type == cJSON_Array) {
            string strResult = "";
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                strResult = cJSON_GetArrayItem(json,0)->valuestring;
            }
            if(strResult == "OK") {
                m_cbc.success();
                return true;
            } 
            cJSON* pError = cJSON_CreateObject();    
            cJSON_AddStringToObject(pError, "message", "unknown");
            cJSON_AddNumberToObject(pError, "code", -1);
            m_cbc.error(pError);
            cJSON_Delete(pError);
        }
    }
    if(content == "write") {
        m_cbc.success();
    }
    return true;
}